package cn.me.alphamq.nameserver.task.service;

import cn.me.alphamq.common.constant.GlobalConstant;
import cn.me.alphamq.nameserver.cache.Container;
import cn.me.alphamq.nameserver.constant.NameServerConstant;
import cn.me.alphamq.nameserver.store.ServiceInstance;
import cn.me.alphamq.nameserver.store.ServiceInstanceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 移除非正常的服务实例的任务类
 *
 * @author f
 */
public class ServiceInstanceRemoveTask implements Runnable {

    private static final Logger log = LoggerFactory.getLogger(ServiceInstanceManager.class);

    /**
     * 在 当前时间戳 - 最后一次发送心跳包的时间戳 > TIME_OUT_STEP 时，认为服务实例宕机
     */
    private static final int TIME_OUT_STEP =
            GlobalConstant.SERVICE_HEART_BEAT_TIME_STEP * NameServerConstant.TIME_OUT_FACTOR;

    /**
     * 启动任务
     */
    public static void startTask() {
        // TODO 后面可以使用线程池来管理定时任务
        new Thread(new ServiceInstanceRemoveTask(), "invalid-server-remove-task-thread").start();
    }

    @Override
    public void run() {
        while (true) {
            // 休眠
            try {
                TimeUnit.SECONDS.sleep(NameServerConstant.DETECT_ABNORMAL_INSTANCE_TIME_STEP);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            // 检测非正常的服务实例，并进行删除
            Map<String, ServiceInstance> serviceInstanceMap = Container.getServiceInstanceManager().getServiceInstanceMap();
            long currTimestamp = System.currentTimeMillis();
            Iterator<String> iterator = serviceInstanceMap.keySet().iterator();
            while (iterator.hasNext()) {
                String brokerIdentification = iterator.next();
                ServiceInstance serviceInstance = serviceInstanceMap.get(brokerIdentification);
                Long lastHeartBeatTimestamp = serviceInstance.getLastHeartBeatTimestamp();
                // 如果服务实例宕机，则移除它
                if (lastHeartBeatTimestamp == null || currTimestamp - lastHeartBeatTimestamp > TIME_OUT_STEP) {
                    iterator.remove();
                    log.info("service instance [{}] is removed", brokerIdentification);
                }
            }
        }
    }
}
